import cv2 as cv
import numpy as np
import math
# import matplotlib.pyplot as plt
import time
import copy


def test_imshow(temp_img, scale_percent=100, cv_show=False, save_img=True,name ='test',wait=0):
    '''
    用于测试的函数，将按照百分比缩放的图片显示出来
    '''
    if save_img:
        cv.imwrite("./images/results/"+name+str(time.time())+".jpg", temp_img)
        return
    if cv_show:
        if scale_percent == 0:
            cv. imshow("img", cv.resize(temp_img,
                                        (480, 270), interpolation=cv.INTER_AREA))
        else:
            width = int(temp_img.shape[1] * scale_percent / 100)
            height = int(temp_img.shape[0] * scale_percent / 100)
            dim = (width, height)
            cv.imshow("img", cv.resize(
                temp_img, dim, interpolation=cv.INTER_AREA))
        cv.waitKey(wait)
        cv.destroyAllWindows()
    else:
        if temp_img.ndim == 3:
            temp_img = cv.cvtColor(temp_img, cv.COLOR_BGR2RGB)
        # plt.imshow(temp_img)
        # plt.show()

    # cv.waitKey(0)

def sorted_boxes_by_area(dt_boxes, texts):
    """
    根据面积排序
    """
    num_boxes = len(dt_boxes)
    _boxes =  dt_boxes
    for j in range(num_boxes - 1):
        for i in range(num_boxes - 1 -j):
            points = copy.deepcopy(_boxes[i])
            img_crop_width_a = int(
            max(
                np.linalg.norm(points[0] - points[1]),
                np.linalg.norm(points[2] - points[3])))
            img_crop_height_a = int(
                max(
                    np.linalg.norm(points[0] - points[3]),
                    np.linalg.norm(points[1] - points[2])))
            points = copy.deepcopy(_boxes[i+1])
            img_crop_width_b = int(
            max(
                np.linalg.norm(points[0] - points[1]),
                np.linalg.norm(points[2] - points[3])))
            img_crop_height_b = int(
                max(
                    np.linalg.norm(points[0] - points[3]),
                    np.linalg.norm(points[1] - points[2])))
            if abs(img_crop_width_a* img_crop_height_a < img_crop_width_b * img_crop_height_b):
                tmp = texts[i]
                texts[i] = texts[i + 1]
                texts[i + 1] = tmp
                tmp = _boxes[i]
                _boxes[i] = _boxes[i + 1]
                _boxes[i + 1] = tmp
    return _boxes,texts

def sorted_boxes_by_coor(dt_boxes):
    """
    Sort text boxes in order from top to bottom, left to right
    args:
        dt_boxes(array):detected text boxes with shape [4, 2]
    return:
        sorted boxes(array) with shape [4, 2]
    """
    num_boxes = dt_boxes.shape[0]
    sorted_boxes = sorted(dt_boxes, key=lambda x: (x[0][1], x[0][0]))
    _boxes = list(sorted_boxes)

    for i in range(num_boxes - 1):
        if abs(_boxes[i + 1][0][1] - _boxes[i][0][1]) < 10 and \
                (_boxes[i + 1][0][0] < _boxes[i][0][0]):
            tmp = _boxes[i]
            _boxes[i] = _boxes[i + 1]
            _boxes[i + 1] = tmp
    return _boxes
def filte_box_by_coor(dt_boxes, texts,size_y):
    """
    根据从左往右,从上到下的顺序
    """
    filte_line = 0.55 * size_y
    num_boxes = len(dt_boxes)
    _boxes = []
    _texts = []
    for box,txt in zip(dt_boxes,texts):
            if box[0][1]<filte_line:
                _boxes.append(box)
                _texts.append(txt)
    return _boxes,_texts

def lines(width, height):
    '''
    return: if True ,reversed
    '''
    if width > height:
        return width, height, False
    else:
        return height, width, True


def calculate_len(box, to_int=False):
    # temp1 = ((y3-y2)**2+(x3-x2)**2)**0.5
    # temp2 = ((y2-y1)**2+(x2-x1)**2)**0.5
    # width = max(temp1, temp2)
    # height = min(temp1, temp2)
    # box = perspective.order_points(box)
    [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] = box
    width = ((y3-y2)**2+(x3-x2)**2)**0.5
    height = ((y2-y1)**2+(x2-x1)**2)**0.5
    reverse = False
    if width < height:
        reverse = True
        width, height = height, width
    if to_int:
        return int(width), int(height), reverse
    else:
        return width, height, reverse

def calculate_centre(box, to_int=False):
    # temp1 = ((y3-y2)**2+(x3-x2)**2)**0.5
    # temp2 = ((y2-y1)**2+(x2-x1)**2)**0.5
    # width = max(temp1, temp2)
    # height = min(temp1, temp2)
    # box = perspective.order_points(box)
    [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] = box
    max_x = max(x1,x2,x3,x4)
    min_x = min(x1,x2,x3,x4)
    max_y = max(y1,y2,y3,y4)
    min_y = min(y1,y2,y3,y4)
    centre_x = (max_x+min_x)/2
    centre_y = (max_y+min_y)/2
    return centre_x,centre_y

def cal_distance(p1, p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) + math.pow((p2[1] - p1[1]), 2))

def crop_rotate_box(box, img,angle=0):
    width, height, _ = calculate_len(box, to_int=True)

    # box = perspective.order_points(box)
    src_pts = box.astype("float32")

    dst_pts = np.array([[0, height-1],
                        [0, 0],
                        [width-1, 0],
                        [width - 1, height - 1]], dtype="float32")
    M = cv.getPerspectiveTransform(src_pts, dst_pts)

    warped = cv.warpPerspective(img, M, (width, height))
    if angle != 0:
        warped = rotated_img(warped,angle)
    return warped


def rotate_img(img, angle=180):

    if angle == abs(90):
        h, w = img.shape[:2]
        padding = (w - h) // 2
        center = ((w // 2), (h // 2))

        img_padded = np.zeros(shape=(w, h, 3), dtype=np.uint8)
        img_padded[padding:padding+h, :, :] = img

        # test_imshow(img_padded, scale_percent=20)
        M = cv.getRotationMatrix2D(center, angle, 1)
        rotated_padded = cv.warpAffine(img_padded, M, (w, h))

        output = rotated_padded[:w-padding, :h, :]

    else:
        output = cv.flip(img, -1)

    return output

def rotated_img(image, angle=180):
    (h,w) = image.shape[:2]
    (cx,cy) = (w/2,h/2)
    
    #设置旋转矩阵
    M = cv.getRotationMatrix2D((cx,cy),-angle,1.0)
    cos = np.abs(M[0,0])
    sin = np.abs(M[0,1])
    
    # 计算图像旋转后的新边界
    nW = int((h*sin)+(w*cos))
    nH = int((h*cos)+(w*sin))
    
    # 调整旋转矩阵的移动距离（t_{x}, t_{y}）
    M[0,2] += (nW/2) - cx
    M[1,2] += (nH/2) - cy
    
    return cv.warpAffine(image,M,(nW,nH))

